/*
 * Copyright (c) 2020 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU)
 * OS-Lab-2020 (i.e., ChCore) is licensed under the Mulan PSL v1.
 * You can use this software according to the terms and conditions of the Mulan PSL v1.
 * You may obtain a copy of Mulan PSL v1 at:
 *   http://license.coscl.org.cn/MulanPSL
 *   THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 *   IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 *   PURPOSE.
 *   See the Mulan PSL v1 for more details.
 */

// Simple command-line kernel monitor useful for
// controlling the kernel and exploring the system interactively.

#include <common/printk.h>
#include <common/types.h>

static inline __attribute__ ((always_inline))
u64 read_fp()
{
	u64 fp;
	__asm __volatile("mov %0, x29":"=r"(fp));
	return fp;
}

__attribute__ ((optimize("O1")))
int stack_backtrace()
{
	u64 fp_sb, fp0, fp1, fp2, fp3, fp4, fp5, fp_m;
	u64 lr0, lr1, lr2, lr3, lr4, lr5, lr_m;
	u64 p0, p1_1, p1_2, p2_1, p2_2, p3_1, p3_2, p4_1, p4_2, p5_1, p5_2, pm;
	printk("Stack backtrace:\n");
	fp_sb = read_fp();
	fp0 = *(u64 *)fp_sb;
	lr0 = *(u64 *)(fp_sb + 8);
	p0 = 0;
	printk("LR %lx FP %lx Args %lx %lx %lx %lx %lx\n", lr0, fp0, p0, 0, 0, 0, 0);

	fp1 = *(u64 *)fp0;
	lr1 = *(u64 *)(fp0 + 8);
	p1_1 = *(u64 *)(fp0 + 16);
	p1_2 = *(u64 *)(fp0 + 24);
	printk("LR %lx FP %lx Args %lx %lx %lx %lx %lx\n", lr1, fp1, p1_1, p1_2, 0, 0, 0);



	fp2 = *(u64 *)fp1;
	lr2 = *(u64 *)(fp1 + 8);
	p2_1 = *(u64 *)(fp1 + 16);
	p2_2 = *(u64 *)(fp1 + 24);
	printk("LR %lx FP %lx Args %lx %lx %lx %lx %lx\n", lr2, fp2, p2_1, p2_2, 0, 0, 0);


	fp3 = *(u64 *)fp2;
	lr3 = *(u64 *)(fp2 + 8);
	p3_1 = *(u64 *)(fp2 + 16);
	p3_2 = *(u64 *)(fp2 + 24);
	printk("LR %lx FP %lx Args %lx %lx %lx %lx %lx\n", lr3, fp3, p3_1, p3_2, 0, 0, 0);


	fp4 = *(u64 *)fp3;
	lr4 = *(u64 *)(fp3 + 8);
	p4_1 = *(u64 *)(fp3 + 16);
	p4_2 = *(u64 *)(fp3 + 24);
	printk("LR %lx FP %lx Args %lx %lx %lx %lx %lx\n", lr4, fp4, p4_1, p4_2, 0, 0, 0);


	fp5 = *(u64 *)fp4;
	lr5 = *(u64 *)(fp4 + 8);
	p5_1 = *(u64 *)(fp4 + 16);
	p5_2 = *(u64 *)(fp4 + 24);
	printk("LR %lx FP %lx Args %lx %lx %lx %lx %lx\n", lr5, fp5, p5_1, p5_2, 0, 0, 0);
	
	fp_m = *(u64 *)fp5;
	lr_m = *(u64 *)(fp5 + 8);
	pm = *(u64 *)(fp5 + 16);
	printk("LR %lx FP %lx Args %lx %lx %lx %lx %lx\n", lr_m, fp_m, pm, 0, 0, 0, 0);

	return 0;
}
